Sixel + Kitty support for "fine resolutions" - #42
Conversation
|
Very interesting! What is your go-to terminal emulator for testing sixel support? |
|
I've only toyed with a few so far, see last column "graphics" of this chart https://ucs-detect.readthedocs.io/results.html, plan to add "Graphics" column in README compatibility table as I go through them. I think I got resizing working well, to determine size and to clear old image, not sure about mode switching (F5-F8), needs testing. |
|
@vxgmichel I have finished a grueling amount of refinement, it was much harder than I imagined, but sixel and kitty support are working well and tested on all linux terminals, I'll check windows and macos soon, video: https://www.jeffquast.com/sixel-and-kitty-graphics.mp4
also, There are new environment variable-enabled options GAMBATERM_PROFILE_DIR and GAMBATERM_DUMP_FRAMES, this has helped me write the tests and do troubleshooting of the blitter, graphics modes, etc, so I will keep them in, though they are a bit cumbersome to use, I depended on them often. There are also some environment variables for limits on maximum scale, which approximates about the same size as "text mode" scale for most terminals -- terminals in "BAD_TEXT", group with font corruption never switch to text mode (unless backspace is pressed) and so we must set a reasonable size limit there. mlterm is also poor performing and good emulator to test "auto scaling" with. |
.. but, syncterm doesn't support kitty keyboard protocol, i temporarily enabled a "warn and continue", to test syncterm's sixel support, but that's for another time..
|
Wow that looks great! What a crazy amount of work you pulled off oO I'm quite busy at the moment, so I apologize for not giving this PR the attention it deserves. I'm also curious about the autoscaler, do you test it with CPR sync enabled? Because as far as I remember, the FPS can drop for two reasons:
Now, the typical CPU usage of the emulator is 4% and the video (i.e the blitter) is 1%, so at 1x speed, scenario 1 is pretty unlikely, unless the remote terminal or network is very slow and a couple of MB of data are already waiting to be processed in the client and/or server TCP buffers, causing the run loop to block on the TCP write. In that case however, a couple of MB is quite a lot of frames so it's likely that the game already became unplayable, which is why I'd like to enable CPR sync default, with the solution described in #31:
Do you see things the same way? This subject is getting a bit too complex to easily reason about it, I should document this better at some point. Also we've been discussing many rendering strategies (including sextants and octants), do you think we can always come up with a way to properly decide what's the best one for a given terminal in a given context? Or should we allow users to switch between them? I'm still confused about what to do with the UI, and what the user experience should be. Ideas are welcome :) |
|
I will test/integrate with When very busy with encoding graphics at scale as high as 11x, CPU usage of gambaterm's video encoding can also be as high as 70%, bandwidth as high as 3,000KB/s. Instead of dropping any frames, I've been lowering the scaling of graphics, but dropping video frames or going half-speed might be better, I'll experiment with it. As for Octants and Sextants, I think Octants might be avoided because we can't reliably detect whether it is supported,
Auto-switching between text and graphics protocols is good UX, that it always fits in the window and always has correct colors and aspect ratio. The only issue is that it would be really hard to communicate to the user, "if you make your window large enough, and font small enough, it will improve the FPS and lower bandwidth, or, that If you make your font smaller, it will switch to text mode and the picture will get larger ?! I'll do my best to document about it in the README I did have backspace/delete key cycling between available graphics modes, but I removed it as I tried to clean up and simplify, because I felt there was no need to switch modes other than for developer testing (offered by GAMBATERM_FORCE_SIXEL=1 or GAMBATERM_FORCE_KITTY=1 env values) |
FYI, mintty has a fairly simple protocol for detecting glyph support, using an OSC 7771 sequence. I don't think it's really practical for querying large ranges of glyphs, although you could probably get by with just querying the first and last character of the glyph set you want to use. I also don't think any other terminals support it (other than mintty forks), but if there was significant demand for this kind of functionality, it probably has more chance of being adopted. ETA: If you want to do something with sextants, it's worth noting that you could do that more efficiently with a DRCS character set, support for which can easily be detected with a DA1 query. |
|
Thanks @j4james, I checked on DRCS of all terminals tested by https://ucs-detect.readthedocs.io/results.html, 5 report support, but I think 3 of those are in error. I hope I'm wrong but the support seems low from first look
|
|
@jquast Note that sixel is both a binary-to-text encoding (akin to base64), as well as the name of an image protocol that uses that encoding. Honestly not a very good name - it'd be like iTerm or Kitty naming their image protocol Base64. But it was originally named DECwriter Graphics (after the printer that first supported it), which is even worse IMO. Anyway my point is that DRCS soft fonts are completely unrelated to the Sixel image protocol - they just happen to use the same binary-to-text encoding. So it's perfectly normal for a terminal to support one and not the other. Almost all DEC terminals supported some form of soft font, but few support the Sixel image protocol. As for terminal emulators supporting DRCS, the ones I've personally tested successfully include KoalaTerm, MLTerm, PowerTerm, Reflection Desktop, RLogin, VTStar, and Windows Terminal. I believe Kermit95 and Contour have also recently added support, although I haven't tested either of them yet. I'm fairly certain Mintty doesn't support DRCS, and I don't see any sign of extension 7 in their DA1 report. I'm not sure about AbsoluteTelnet or SecureCRT. But feel free to ignore this if you're not interested. I was just throwing it out as an idea in case anyone felt inspired to give it a try. |
|
I always appreciate your thoughts @j4james, I recorded all DA1 response from mintty and others by direct interrogation/use, and, it is not congruent with the source code of mintty. I've been looking at it for quite some time, seems to be a bug with windows conhost.exe overrides, but it appears to my Windows 11 machine that conhost.exe/ConPTY overrides the DA1 response, mintty matches the DA1 response of your commit from 2023 https://github.com/microsoft/terminal/blob/3c3b1aac02320f49f6887f08e6d6d1d56132b1ef/src/terminal/adapter/adaptDispatch.cpp#L1500 on 10.0.26100.8328 (Windows 11 24H2). From mintty: |
limits are in KB/s matching the status bar
|
OK, I see your problem now. If you're testing a Windows-based terminal that's dependent on conpty, it needs to be using a modern pass-through version of the library, otherwise you're just testing conpty itself. It's like trying to test the terminal's functionality from within tmux. With mintty, it used to be possible to bypass conpty (at least for running WSL) by using a wsltty build, but that apparently changed in version 3.8.0, so I think it's also limited by conpty now. And they don't really support using a modern version of conpty - their suggested solution is to replace the system libraries, which I wouldn't recommend. Other Windows-based terminals are generally better, but if they have a Linux version, it's easier to just test on Linux. And terminals with a built-in ssh or telnet are also fine, because then you're connecting directly to your test system, and conpty isn't a factor. |
|
I do use an arch linux docker container and Xvfb to test a majority of terminals, but of course mintty isn't available there. That I am testing conpty instead of a native emulator's true capabilities is precisely the point of ucs-detect, to test the software as it is distributed and not theoretical capabilities if it's build and installation were customized I'll just make a note about the unreliable results of mintty and other CONPTY-based terminals in the ucs-detect documentation. jquast/ucs-detect#52 |
Do you know how I could reproduce this? I'd like to investigate this in order know if I can enable CPR sync by default.
Oh I didn't realize that. Let me try to summarize:
And then I'm not sure what to write for kitty, did you manage to use compression in a way so that the required bandwidth do not increase with scaling?
You meant "if you make your window small enough it will improve the FPS and lower the bandwidth"? Because a small window means small scaling, right? Something like this:
But yes that's my main concern, especially because we first need to detect which rendering method the terminal support in order to provide users with their available options; I'm not sure that a README would really help here. |
|
Well I realize now that the “click” and “pops” I’m hearing especially with high pitched square wave audio is not an artifact of “cpu usage too high causing dropped audio frames”, rather an effect of the resampling/audio pipeline. I ended up spending a lot of time looking at the wrong place. I’m working on rolling back all of the extra options and I’ll round it out for review in a few days, frame dropping works fine, graphics work fine, even at largest scale with —cpr-sync. I have been working on carving larger graphics images for kitty protocol into “bands” of ~256K each, so that the rendering pipeline never encodes a full frame but just pieces at a time, and yielding until next frame anytime the audio buffer is detected under 20% full (it doesn’t know, it just projects according to time elapsed, a sort of “time budget” for the renderer) although it causes a small amount of “tearing” on very busy frames it’s much smoother during that process, usually there are some audio clicks and visual jitter here that this banding fixes, I’m doing profiling and debugging on that to see if the complexity is worth it and I’ll share when complete. sizel has a kind of scaling built in that is linear, so 1x vs. 11x scaling is about the same bandwidth there, and so sixel is preferred over kitty when both are supported. Kitty on the other hand is bilinear scaling, I’ve given up trying to use the protocol’s scaling, even with “pixel padding” to ensure scaling is done at exact integers it is still blurry. so anyway it seems all graphic scales work really well locally, and, we can set an optional bandwidth limit for servers, which drops frames when busy to limit it, still working out the “banding” issues but it appears it also reduces total KB/s because it no longer tries to encode and send whole-screen images but only partial, slightly lower fidelity but these are busy screen like when “sliding” to new screens in Zelda |
todo -- some bands are sometimes not redrawn when they should have been.
only happens at the flashing mob scene in zelda with the
flashing guy is between two bands?!
for profiling it can be turned on or off but so far the results are very good and this will probably just become "always on" instead
Closes #30, WIP still under testing and review